local message = require 'jass.message'
local runtime = require 'jass.runtime'
local dbg = require 'jass.debug'
local jass = require 'jass.common'
local japi = require 'jass.japi'

local handle_manager = handle_manager_class:create()

local mover = { }
setmetatable(mover,mover)
ac.mover = mover

mover.class = { }
mover.handle_list  = message.create_list()
mover.allmovers = { }
mover.gchash = 0
mover.allcount = 0
mover.mover_map = setmetatable({ }, { __mode = 'kv' }) -- 弱引用 记录 handle = mover

--- 输出
function mover:__tostring()
    return ("运动器[%s]"):format(self._src or 'C')
end 

function mover.j_mover(handle)
    if handle and handle ~= 0 then 
        return mover.mover_map[handle]
    end
end

function mover.enum_range(point,range)
    local x,y = point:get()
    return message.list_enum_range(mover.handle_list, x, y, range) or { }
end

function mover.init()
    require 'types.mover.line'
    require 'types.mover.point'
    require 'types.mover.bezier'
    require 'types.mover.target'
    require 'types.mover.round'
end 

local mt = { }
mover.__index = mt 

--类型
mt.type = 'mover'

--所有者
mt.owner = nil 

--运动对象
mt.mover = nil 

--刷新周期
mt.frame = 0.03

mt.height = 0

--是否可旋转
mt.turn_flag = true

-- 时间(-1为无限)
mt.time = 30

-- 暂停计数器
mt.pause_count = 0

-- 体积 (体积 用来代表大小)
mt.collision = 32.0

--- 执行事件
function mt:notify(name,...)
    local func = self[name]
    if func then 
        return select(2, xpcall(func, runtime.error_handle, self, ...))
    end 
end 

--- 判断运动器是否是目标的敌对
function mt:is_enemy(dest)
    if not self.source then 
        return false
    end 
    return self.source:is_enemy(dest)
end

--- 判断运动器是否是目标的友军
function mt:is_ally(dest)
    if not self.source then 
        return false
    end 
    return self.source:is_ally(dest)
end

--- 暂停中
function mt:is_pause()
    return self.pause_count > 0
end

--- 暂停
function mt:set_pause(flag)
    if flag == true then 
        self.pause_count = self.pause_count + 1
        if self.pause_count == 1 then 
            if self.delay_timer then 
                self.delay_timer:pause()
            end 
        end 
    else 
        self.pause_count = self.pause_count - 1
        if self.pause_count == 0 then 
            if self.delay_timer then 
                self.delay_timer:resume()
            end 
        end 
    end 
end 

--- 获取运动临界值
--- @return number minx
--- @return number miny
--- @return number maxx
--- @return number maxy
function mt:get_bound()
    return ac.rect.map:get()
end 

-- 获取位置
function mt:get_point()
    if self.removed then 
        return self._last_point
    end
    return self.mover:get_point()
end

-- 设置位置
function mt:set_point(point)
    if self.removed then 
        return
    end
    self._last_point = point 
    self.mover:set_point(point)
end

-- 设置高度
function mt:set_height(height)
    if self.removed then 
        return
    end
    self._last_height = height
    self.mover:set_height(height)
end 

-- 获取高度
function mt:get_height()
    if self.removed then 
        return self._last_height
    end
    return self.mover:get_height()
end 

-- 获取大小
function mt:get_scale()
    if self.removed then 
        return 1.0
    end
    return self.mover:get_scale()
end

-- 获取大小
function mt:get_impact_point()
    if self.removed then 
        return self._last_point
    end
   local point = self:get_point()
   local height = self:get_height()
   local scale = self:get_scale()
   local collision = self.collision
   point.z = point:get_height() + height + (scale * collision / 2)
   return point
end

-- 旋转值
function mt:get_rotate()
    if self.removed then 
        return 0,0,0
    end
    if self.mover.get_rotate then 
        return self.mover:get_rotate()
    else
        return 0,0,self.mover:get_facing()
    end
end

-- 旋转
function mt:set_rotate(x,y,z)
    if self.removed then 
        return 
    end
    if self.mover.rotate then 
        self.mover:set_rotate(x,y,z, true)
    elseif self.turn_flag then 
        self.mover:set_facing(z)
    end
end

-- 获取运动器的handle
function mt:get_mover_handle()
    if not self.mover_handle then 
        self.mover_handle = self.mover.handle
    end 
    return self.mover_handle
end 

-- 初始化
function mt:init()
    
    local index = handle_manager:allocate()
    self._index = index 
    self.gchash = index 
    dbg.gchash(self, index)
    if not self.mover then
        local angle = self.target and self.start / self.target:get_point()
        self.start = self.start:get_point()
        self.need_remove_mover = true
        self.mover = self.start:effect
        {
            model = self.model or '',
            rotate = {0, 0, angle or self.face or self.angle or 0},
            size = self.size,
            height = self.height,
            show_state = self.show_state,
        }
    end
    
    local handle = self:get_mover_handle()
    if handle and handle ~= 0 then 
        if not mover.mover_map[handle] then 
            message.list_add(mover.handle_list,handle)
        end
        mover.mover_map[handle] = self
    end 

    if self.time > 0 then 
        self.delay_timer = ac.wait(self.time * 1000,function() 
            self:finish()
        end)
    end 

    self.cycle_timer = ac.loop(self.frame * 1000,function()
        if self:is_pause() then 
            return false 
        end
        self:move()
    end)

    self._last_point = self:get_point()
    self._last_height = self:get_height()

    mover.has_alive = true

    mover.allmovers[self] = true
    mover.allcount = mover.allcount + 1 
end 

-- 获取运动器类型
function mt:get_mover_type()
    return self.mover.type
end 

-- 移动
function mt:move()
    self:notify 'on_move'
end 

-- 杀死
function mt:kill()
    if self.has_alive then 
        self.has_alive = false
        self:notify 'on_kill'
        self:remove()
    end 
end 

-- 停止
function mt:finish()
    if self.has_alive then 
        self:notify 'on_finish'
    end
    self:remove()
end

-- 发射
function mt:launch()
    if not self.has_launch and not self.removed then 
        self.has_launch = true
        self:notify 'on_launch'
        --self.cycle_timer:on_timer()
    end 
    return self
end

-- 删除运动器
function mt:remove()
    
    if self.removed then 
        return 
    end 

    self.removed = true 

    local handle = self:get_mover_handle()

    mover.mover_map[handle] = nil 
    message.list_remove(mover.handle_list, handle)

    if self.cycle_timer then 
        self.cycle_timer:remove()
    end
    if self.delay_timer then 
        self.delay_timer:remove()
    end 
    if self.need_remove_mover then 
        self.mover:remove()
    end 

    self:notify 'on_remove'

    local index = self._index 
    handle_manager:free(index)

    mover.allmovers[self] = nil
    mover.allcount = mover.allcount - 1
end 

-- 创建运动器
function mover:__call(name)
    local class = mover.class[name] or self
    return function(info)
        local m = setmetatable(info,class)
        m:init()
        return m:launch()
    end
end

return mover 